
package bibliotheque.server;

import bibliotheque.transaction.TransactionId;
import bibliotheque.document.DocumentId;
import bibliotheque.transaction.TransactionManager;
import bibliotheque.wave.WaveAction;
import bibliotheque.wave.WaveAgent;

public class FreeAction extends WaveAction {
    private TransactionId tid;
    private DocumentId did;
    private TransactionManager.FreeState state;
    
    public FreeAction(TransactionId tid,DocumentId did) {
        this.tid = tid;
        this.did = did;
        this.state = TransactionManager.FreeState.NOTFOUND;
    }
    
    public void PropagateBefore(WaveAgent agent)throws Exception {
        Server server ;
        if (agent instanceof Server) {
            server = (Server)agent;
            try {
                server.mutex.acquireUninterruptibly();
                if(server.state == Server.State.SUBSCRIBING) throw new Exception("Free failed cause server state is subscribing.");
                if(server.state == Server.State.STARTING) throw new Exception("Free failed cause server state is starting.");
                if(server.state == Server.State.STOPPING) throw new Exception("Free failed cause server state is stopping.");
                if(server.state == Server.State.STOP) throw new Exception("Free failed cause server state is stopped.");
                
                if(this.state == TransactionManager.FreeState.NOTFOUND) this.state = server.transaction_manager.FreeInit(this.wave_id, tid, did);
                
                
            } catch (Exception ex) {
                server.ErrorOccured(ex.getMessage());
                throw ex;
            } finally {
                server.mutex.release();
            }
        }
    }
    
    public void Acknowledge(WaveAgent agent) throws Exception {
        Server server ;
        if (agent instanceof Server) {
            server = (Server)agent;
            try {
                server.mutex.acquireUninterruptibly();
                if(server.state == Server.State.SUBSCRIBING) throw new Exception("Free failed cause server state is subscribing.");
                if(server.state == Server.State.STARTING) throw new Exception("Free failed cause server state is starting.");
                if(server.state == Server.State.STOPPING) throw new Exception("Free failed cause server state is stopping.");
                if(server.state == Server.State.STOP) throw new Exception("Free failed cause server state is stopped.");
                
                server.transaction_manager.FreeUpdate(this.wave_id, this.state);
                
            } catch (Exception ex) {
                server.ErrorOccured(ex.getMessage());
                throw ex;
            } finally {
                server.mutex.release();
            }
        }
    }
    
    public void LocalEnd(WaveAgent agent) throws Exception {
        Server server ;
        if (agent instanceof Server) {
            server = (Server)agent;
            try {
                server.mutex.acquireUninterruptibly();
                if(server.state == Server.State.SUBSCRIBING) throw new Exception("Free failed cause server state is subscribing.");
                if(server.state == Server.State.STARTING) throw new Exception("Free failed cause server state is starting.");
                if(server.state == Server.State.STOPPING) throw new Exception("Free failed cause server state is stopping.");
                if(server.state == Server.State.STOP) throw new Exception("Free failed cause server state is stopped.");
                
                this.state = server.transaction_manager.FreeResult(this.wave_id);
                
            } catch (Exception ex) {
                server.ErrorOccured(ex.getMessage());
                throw ex;
            } finally {
                server.mutex.release();
            }
        }
    }
    
    public void GlobalEnd(WaveAgent agent) throws Exception {
        
        if (agent instanceof Server) {
            Server server = (Server)agent;
            try {
                server.mutex.acquireUninterruptibly();
                if(server.state == Server.State.SUBSCRIBING) throw new Exception("Selection failed cause server state is subscribing.");
                if(server.state == Server.State.STARTING) throw new Exception("Selection failed cause server state is starting.");
                if(server.state == Server.State.STOPPING) throw new Exception("Selection failed cause server state is stopping.");
                if(server.state == Server.State.STOP) throw new Exception("Selection failed cause server state is stopped.");
                
                try {
                    if(this.state == TransactionManager.FreeState.SUCCESS) server.clients.get(this.tid.GetClient()).SetFreeResult(true,this.did);
                    else {
                        InvalidateAction action = new InvalidateAction(this.tid);
                        server.Initiate(action);
                    }
                } catch (Exception ex) {
                    server.ErrorOccured("Free failed cause the client returns an error");
                }
            } catch (Exception ex) {
                server.ErrorOccured(ex.getMessage());
                throw ex;
            } finally{
                server.mutex.release();
            }
        }
    }
    
}
